﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PloobsEngine.SceneControl;
using PloobsEngine.Physics;
using PloobsEngine;
using PloobsEngine.Cameras;
using PloobsEngine.Input;
using Microsoft.Xna.Framework;
using PloobsEngine.Physics.Bepu;
using PloobsEngine.Modelo;
using PloobsEngine.Material;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.Utils;
using PloobsEngine.Features;
using PloobsEngine.Commands;
using PloobsEngineDemo3;
using PloobsEngine.Light;
using BezierApp;
using Etapa1.BezierExperiments;

namespace Etapa1.Screens
{
    public class BezierScreen : SceneScreen
    {
        private BepuPhysicWorld physicWorld;
        private BrutalForceWorld mundo;
        private EngineStuff engine;        
        ICamera cam;

        Vector3 p0 = new Vector3(0, 0, 0);
        Vector3 p1 = new Vector3(0, 0, 1);
        Vector3 p2 = new Vector3(0, 1, 1);
        Vector3 p3 = new Vector3(1, 1, 1);


        public BezierScreen(EngineStuff es)
        {
            this.engine = es;
            physicWorld = new BepuPhysicWorld();
            mundo = new BrutalForceWorld(physicWorld);                                
        }
        
        public override void LoadContent(EngineStuff es)
        {            
            InputAdvanced inp = new InputAdvanced(engine);
            engine.AddComponent(inp);

            base.LoadContent(es);            

            #region Models

            p0 = Vector3.Transform(p0, Matrix.CreateScale(100) * Matrix.CreateTranslation(new Vector3(0, 100, 0)));
            p1 = Vector3.Transform(p1, Matrix.CreateScale(100) * Matrix.CreateTranslation(new Vector3(0, 100, 0)));
            p2 = Vector3.Transform(p2, Matrix.CreateScale(100) * Matrix.CreateTranslation(new Vector3(0, 100, 0)));
            p3 = Vector3.Transform(p3, Matrix.CreateScale(100) * Matrix.CreateTranslation(new Vector3(0, 100, 0)));

            {                

                BezierCurve bc = new BezierCurve(p0, p1, p2, p3);
                bc.Create(EngineStuff.GraphicsDevice);

                VertexBufferModel sm = new VertexBufferModel(bc.VertexBuffer,bc.PrimitiveCount,bc.VertexDeclaration,bc.VertexDeclaration.GetVertexStrideSize(0));
                sm.LoadModelo();
                BezierShader shader = new BezierShader();
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj3 = new SimpleObject(mat, new DummyPhysicObject(), sm);
                mundo.AddObject(obj3);
            }



            {
                Vector3[] cpts = new Vector3[16];
                cpts[0] = new Vector3(-0.75f, -0.75f, -0.50f); 
                cpts[1]  = new Vector3(-0.25f, -0.75f, 0);
                cpts[2] = new Vector3(0.25f, -0.75f, 0);
                cpts[3] = new Vector3(0.75f, -0.75f, -0.50f);

                cpts[4] = new Vector3(-0.75f, -0.25f, -0.75f);
                cpts[5]  = new Vector3(-0.25f, -0.25f, 0.50f);
                cpts[6]  = new Vector3(0.25f, -0.25f, 0.50f);
                cpts[7]  = new Vector3(0.75f, -0.25f, -0.75f);

                cpts[8]  = new Vector3(-0.75f, 0.25f, 0);
                cpts[9] = new Vector3(-0.25f, 0.25f, -0.50f);
                cpts[10] = new Vector3(0.25f, 0.25f, -0.50f);
                cpts[11] = new Vector3(0.75f, 0.25f, 0);

                cpts[12] = new Vector3(-0.75f, 0.75f, -0.50f);
                cpts[13] = new Vector3(-0.25f, 0.75f, -1);
                cpts[14] = new Vector3(0.25f, 0.75f, -1);
                cpts[15] = new Vector3(0.75f, 0.75f, -0.50f);

               for (int i = 0; i < 16; i++)
               {
                   cpts[i] = Vector3.Transform(cpts[i],Matrix.CreateRotationZ(MathHelper.ToRadians(90)) *  Matrix.CreateScale(100) * Matrix.CreateTranslation(new Vector3(0, 50, 0)) );
                }

                BezierSurface bc = new BezierSurface(cpts);
                bc.Create(EngineStuff.GraphicsDevice);

                VertexIndexBufferModel sm = new VertexIndexBufferModel(bc.IndexBuffer, bc.VertexBuffer, bc.VerticesCount, bc.PrimitiveCount, bc.VertexDeclaration, bc.VertexDeclaration.GetVertexStrideSize(0));
                sm.LoadModelo();
                IndexVertexTriangleShader shader = new IndexVertexTriangleShader();
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj3 = new SimpleObject(mat, new DummyPhysicObject(), sm);
                mundo.AddObject(obj3);
            }

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cubo", "..\\Content\\Textures\\blue");
                sm.LoadModelo();
                BoxObject pi = new BoxObject(p0, 1, 10, new Vector3(1));
                pi.isMotionLess = true;
                CustomDeferred shader = new CustomDeferred(false, false, false, false);                
                shader.Initialize();
                IMaterial mat = new Material(shader, MaterialType.DEFERRED);
                IObject obj3 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj3);
            }


            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cubo", "..\\Content\\Textures\\blue");
                sm.LoadModelo();
                BoxObject pi = new BoxObject(p1, 1, 10, new Vector3(1));
                pi.isMotionLess = true;
                CustomDeferred shader = new CustomDeferred(false, false, false, false);
                shader.SpecularIntensity = 0;
                shader.SpecularPower = 0;
                shader.Initialize();
                IMaterial mat = new Material(shader, MaterialType.DEFERRED);
                IObject obj3 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj3);
            }


            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cubo", "..\\Content\\Textures\\blue");
                sm.LoadModelo();
                BoxObject pi = new BoxObject(p2, 1, 10, new Vector3(1));
                pi.isMotionLess = true;
                CustomDeferred shader = new CustomDeferred(false, false, false, false);
                shader.SpecularIntensity = 0;
                shader.SpecularPower = 0;
                shader.Initialize();
                IMaterial mat = new Material(shader, MaterialType.DEFERRED);
                IObject obj3 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj3);
            }


            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cubo", "..\\Content\\Textures\\blue");
                sm.LoadModelo();
                BoxObject pi = new BoxObject(p3, 1, 10, new Vector3(1));
                pi.isMotionLess = true;
                CustomDeferred shader = new CustomDeferred(false, false, false, false);
                shader.SpecularIntensity = 0;
                shader.SpecularPower = 0;
                shader.Initialize();
                IMaterial mat = new Material(shader, MaterialType.DEFERRED);
                IObject obj3 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj3);
            }

            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cenario");
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(Vector3.Zero, sm);                
                CustomDeferred shader = new CustomDeferred(false, false, false, false);
                shader.SpecularIntensity = 0;
                shader.SpecularPower = 0;
                shader.Initialize();
                IMaterial mat = new Material(shader, MaterialType.DEFERRED);
                IObject obj3 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj3);
            }            

            #endregion            

            cam = new CameraFirstPerson(true);            
            cam.FarPlane = 3000;

            LightThrowBepu lt = new LightThrowBepu(mundo, engine);         

            #region NormalLight
            DirectionalLight ld1 = new DirectionalLight(Vector3.Left, Color.White);
            DirectionalLight ld2 = new DirectionalLight(Vector3.Right, Color.White);
            DirectionalLight ld3 = new DirectionalLight(Vector3.Backward, Color.White);
            DirectionalLight ld4 = new DirectionalLight(Vector3.Forward, Color.White);
            DirectionalLight ld5 = new DirectionalLight(Vector3.Down, Color.White);
            float li = 0.4f;
            ld1.LightIntensity = li;
            ld2.LightIntensity = li;
            ld3.LightIntensity = li;
            ld4.LightIntensity = li;
            ld5.LightIntensity = li;
            mundo.AddLight(ld1);
            mundo.AddLight(ld2);
            mundo.AddLight(ld3);
            mundo.AddLight(ld4);
            mundo.AddLight(ld5);
            #endregion

            ////Criacao de uma Tecnica
            DeferredRenderTechnic dr = new DeferredRenderTechnic(engine);
            
            IRenderTechnic[] rt = new IRenderTechnic[] { dr };
            this.RenderTechnics = rt;
            //dr.isDebug = true;
            mundo.AddCamera(cam);
            this.World = mundo;
        }

        
    }
}

